package com.fone.player.airone;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;

import com.fone.player.ApplicationManage;
import com.fone.player.play.FonePlayerActivity;
import com.fone.player.util.L;

/**
 * 
 * DLNA视频投放入口，移植于3.4
 * 
 * @author kongxiaojun
 * @since 2014-4-24
 */
public class AirOne {

	static AirOne one;
	static Vector<AirServerDevice> datas = new Vector<AirServerDevice>();
	static String TAG = "AIRONE";
	private IAironeService mService;
	private IDeviceChangedListener iDCListener;
	BroadcastReceiver airone_receicer;

	private AirOne() {
		if (!isStoped)
			new Thread() {
				public void run() {
					AirOne.this.start();
				}
			}.start();

	}

	/**
	 * 开启投放服务
	 * 
	 * @return void
	 * @throws
	 */
	private void start() {

		IntentFilter filter = new IntentFilter();
		filter.addAction(AironeService.ACTION);
		if (airone_receicer != null) {
			try {
				if (FonePlayerActivity.FonePlayerActivityInstance.get() != null) {
					FonePlayerActivity.FonePlayerActivityInstance.get().unregisterReceiver(airone_receicer);
				}
			} catch (Exception e) {

			}
			airone_receicer = null;
		}
		airone_receicer = new BroadcastReceiver() {

			@Override
			public void onReceive(Context context, Intent intent) {
				AirServerDevice dev = (AirServerDevice) intent.getSerializableExtra(AironeService.TAG);
				boolean add = intent.getBooleanExtra(AironeService.TYPE, true);
				// if( !dev.server_name.equals("Appletv001") )
				// return;
				if (dev == null || TextUtils.isEmpty(dev.server_ip_addr) || TextUtils.isEmpty(dev.server_uid)){
					return;
				}
				L.i(TAG, "", "airone service: notify:" + dev);
				if (add) {

					Iterator<AirServerDevice> it = datas.iterator();
					boolean isAdd = true;
					// 去除重复的
					while (it.hasNext()) {
						// if(
						// (st.server_ip_addr.equals(dev.server_ip_addr)||st.server_name.equals(dev.server_name))
						// && st.proto != dev.proto )
						// {
						// return;
						// }
						AirServerDevice st = it.next();
						if (st.server_ip_addr.equals(dev.server_ip_addr)) {
							// 两个设备ip相同
							if (st.proto == dev.proto) {// 协议相同
								if (st.server_uid.equals(dev.server_uid)) {
									st.copyTo(dev);
									it.remove();
									break;
								}
							} else {
								if (st.proto == 0) {// 如果已经存在的是airplay就删除airplay的，再添加dlna进入设备列表
									it.remove();
									break;
								} else {// 如果已存在的是dlna的就返回不添加
									isAdd = false;
									break;
								}
							}

						}
					}
					if (isAdd) {
						datas.insertElementAt(dev, 0);
					}
					L.i(TAG, "dev.logined : ", dev.logined);
					// L.i(TAG,"snsIsLogined : ", fn_Core.snsIsLogined());
					// TODO 检测用户是否登录
					// if (!dev.logined && fn_Core.snsIsLogined()) {
					// loginTv(dev);
					// }
					L.i(TAG, "", "service: datas size:" + datas.size());
				} else {
					Iterator<AirServerDevice> it = datas.iterator();
					while (it.hasNext()) {
						AirServerDevice st = it.next();
						if (st.server_uid.equals(dev.server_uid)) {
							it.remove();
							break;
						}
					}
				}
				if (iDCListener != null)
					iDCListener.changed(dev, add);
			}

		};

		if (FonePlayerActivity.FonePlayerActivityInstance.get() != null) {
			FonePlayerActivity.FonePlayerActivityInstance.get().registerReceiver(airone_receicer, filter);
		}

		ServiceConnection conn = new ServiceConnection() {

			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				mService = IAironeService.Stub.asInterface(service);
				startService(true);
			}

			@Override
			public void onServiceDisconnected(ComponentName name) {
				mService = null;
			}
		};

		if (FonePlayerActivity.FonePlayerActivityInstance.get() != null) {
			final Intent intent = new Intent(FonePlayerActivity.FonePlayerActivityInstance.get(), AironeService.class);
			// FonePlayerActivity.instance.startService(intent);
			FonePlayerActivity.FonePlayerActivityInstance.get().bindService(intent, conn, Context.BIND_AUTO_CREATE);
		}

	}

	public IAironeService getService() {
		return mService;
	}

	/**
	 * get this class's instance
	 * 
	 * @return AirOne's instance
	 * @return AirOne
	 * @throws
	 */
	public static AirOne getInstance() {

		if (one == null) {
			one = new AirOne();
		}
		return one;

	}

	/**
	 * get dlna server number in the lan
	 * 
	 * @return int
	 * @throws
	 */
	public int getSize() {
		return datas.size();
	}

	/**
	 * start dlna service
	 * 
	 * @param start
	 *            if true start service else stop service
	 * @return void
	 * @throws
	 */
	private void startService(final boolean start) {

		new Handler().postDelayed(new Thread() {
			public void run() {
				if (mService == null)
					return;
				if (start)
					try {
						mService.start();
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				else
					try {
						mService.stop();
					} catch (RemoteException e) {
						e.printStackTrace();
					}

			}
		}, 2000);

	}

	/**
	 * 重新搜索设备
	 * 
	 * @return void
	 * @throws
	 */
	public void reSearchDevs() {
		if (mService != null) {
			try {
				mService.stop();
				mService.start();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		} else
			start();
	}

	public boolean isStarted() {
		if (mService != null)
			try {
				return mService.isStarted();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		return false;
	}

	public AirServerDevice getDevice(int position) {
		if (position < 0 || position >= datas.size())
			return null;
		return datas.get(position);
	}

	public int getIndex(String uuid) {
		if (uuid == null)
			return -1;
		else {
			int i = 0;
			for (AirServerDevice t : datas) {
				if (uuid.equals(t.server_uid))
					return i;
				i++;
			}
		}
		return -1;
	}

	public void addDevice(AirServerDevice dev) {
		datas.add(dev);
	}

	private static String intToIp(int i) {

		return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
	}

	/**
	 * 
	 * show a dialog to display dlna devices
	 * 
	 * @param context
	 *            Context
	 * @param listener
	 *            Selected Listener
	 * @return AlertDialog
	 * @throws
	 */
	public AlertDialog showSelectDevices(Context context, final ISelectedListener listener) {

		String[] items = new String[getSize()];
		final boolean[] checks = new boolean[items.length];
		for (int i = 0; i < getSize(); i++)
			items[i] = datas.get(i).server_name + "[" + (datas.get(i).proto == 0 ? "airplay" : "dlna") + "]";

		final AlertDialog dialog = new AlertDialog.Builder(context).setMultiChoiceItems(items, checks, new OnMultiChoiceClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which, boolean isChecked) {
				checks[which] = isChecked;
			}

		}).setPositiveButton("播放", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				listener.onSelected(checks);
			}
		}).setNegativeButton("取消", null).create();

		dialog.show();
		return dialog;
	}

	public AlertDialog showSingleSelectDevices(Context context, final ISelectedListener listener) {

		String[] items = new String[getSize()];
		for (int i = 0; i < getSize(); i++)
			items[i] = datas.get(i).server_name + "[" + (datas.get(i).proto == 0 ? "airplay" : "dlna") + "]";

		final AlertDialog dialog = new AlertDialog.Builder(context).setSingleChoiceItems(items, 0, new OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {

				dialog.dismiss();
				listener.onSelected(which);

			}

		}).create();

		dialog.show();
		return dialog;
	}

	public interface ISelectedListener {
		public void onSelected(boolean[] checks);

		public void onSelected(int index);
	}

	/**
	 * 
	 * get local ip address and port to dlna device request this device to play
	 * local video.
	 * 
	 * @return local ip and port ex:192.168.1.11:9999
	 * @return String
	 * @throws
	 */
	public static String getLocalIpAndPort() {
		return getLocalIP() + ":" + AironeService.PORT;
	}

	/**
	 * 
	 * get wifi address if wifi is connection
	 * 
	 * @param Context
	 * @return wifi ip address ex:192.168.1.11
	 * @throws
	 */
	public static String wifiAddress(Context localContext) {
		Object[] arrayOfObject;
		String str = null;
		if (localContext != null) {
			WifiManager ocheck = ((WifiManager) localContext.getSystemService("wifi"));
			if (ocheck != null) {
				WifiInfo info = ocheck.getConnectionInfo();
				if (info != null) {
					int i = info.getIpAddress();
					if (i != 0) {
						arrayOfObject = new Object[4];
						arrayOfObject[0] = Integer.valueOf(i & 0xFF);
						arrayOfObject[1] = Integer.valueOf(0xFF & i >> 8);
						arrayOfObject[2] = Integer.valueOf(0xFF & i >> 16);
						arrayOfObject[3] = Integer.valueOf(0xFF & i >> 24);
						str = String.format("%d.%d.%d.%d", arrayOfObject);
					}
				}

			}

		}
		if (str == null) {
			String iptest = null;
			try {
				for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
					NetworkInterface intf = en.nextElement();
					for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
						InetAddress inetAddress = enumIpAddr.nextElement();
						if (!inetAddress.isLoopbackAddress()) {
							iptest = inetAddress.getHostAddress().toString();
							if (!iptest.contains("%") && !iptest.contains("wlan")) {
								str = iptest;
								break;
							}
						}

						L.i("dlna", "get wifi ip:" + inetAddress.getHostAddress().toString());
					}
				}
			} catch (SocketException ex) {
				str = "0.0.0.0";
			}
		}
		L.i("dlna", "get wifi ip:" + str);
		return str;

	}

	/**
	 * 
	 * get local ip address
	 * 
	 * @return ip address ex:192.168.1.11
	 * @throws
	 */
	public static String getLocalIP() {

		String ip_ = wifiAddress(ApplicationManage.getAplicationManageInstance());
		if (ip_ != null)
			return ip_;

		try {
			Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
			while (netInterfaces.hasMoreElements()) {
				NetworkInterface ni = netInterfaces.nextElement();
				Enumeration<InetAddress> ips = ni.getInetAddresses();
				while (ips.hasMoreElements()) {
					InetAddress local = ips.nextElement();

					L.i(TAG, "", "local:" + local);
					L.i(TAG, "", "          isAnyLocalAddress:" + local.isAnyLocalAddress());
					L.i(TAG, "", "          isLinkLocalAddress:" + local.isLinkLocalAddress());
					L.i(TAG, "", "          isLoopbackAddress:" + local.isLoopbackAddress());
					L.i(TAG, "", "          isMCGlobal:" + local.isMCGlobal());
					L.i(TAG, "", "          isMCLinkLocal:" + local.isMCLinkLocal());
					L.i(TAG, "", "          isMCNodeLocal:" + local.isMCNodeLocal());
					L.i(TAG, "", "          isSiteLocalAddress:" + local.isSiteLocalAddress());

					if (!local.isLoopbackAddress() && !local.isLinkLocalAddress()) {
						String ip = local.toString();
						if (ip.startsWith("/"))
							return ip.substring(1);
					}

				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		WifiManager wifiManager = (WifiManager) ApplicationManage.getAplicationManageInstance().getSystemService(Context.WIFI_SERVICE);
		return intToIp(wifiManager.getConnectionInfo().getIpAddress());
	}

	/**
	 * 
	 * DLNA server device change listener
	 * 
	 * @author kongxiaojun
	 * @since 2014-4-24
	 */
	public static interface IDeviceChangedListener {
		public void changed(AirServerDevice dev, boolean add);
	};

	/**
	 * 
	 * set DLNA server device change listener
	 * 
	 * @param listener
	 * @return void
	 * @throws
	 */
	public void setDeviceChangedListener(IDeviceChangedListener listener) {
		iDCListener = listener;
	}

	/**
	 * remove all devices
	 * 
	 * @return void
	 * @throws
	 */
	public void removeAll() {
		datas.removeAllElements();
		iDCListener.changed(null, true);
	}

	/**
	 * get dlna device info by server_uid
	 * 
	 * @param server_uid
	 * @return AirServerDevice
	 * @throws
	 */
	public AirServerDevice getDevice(String uuid) {

		if (uuid != null && datas.size() > 0) {
			for (AirServerDevice dev : datas)
				if (uuid.equals(dev.server_uid))
					return dev;
		}
		return null;
	}

	/**
	 * get all dlna devices
	 * 
	 * @return List<AirServerDevice>
	 * @throws
	 */
	public List<AirServerDevice> getDevices() {
		return datas;
	}

	/**
	 * get checked count
	 * 
	 * @return int
	 * @throws
	 */
	public int getCheckedCount() {
		int aironePlaySize = 0;
		for (AirServerDevice d : datas) {
			if (d.checked) {
				aironePlaySize++;
			}
		}
		return aironePlaySize;
	}

	/**
	 * start air one
	 * 
	 * @return void
	 * @throws
	 */
	public static void Start() {

		isStoped = false;
		new Thread() {
			public void run() {
				getInstance();
			}
		}.start();
	}

	/**
	 * clear all checked devices status
	 * 
	 * @return void
	 * @throws
	 */
	public void resetChecked() {
		for (int i = 0; i < AirOne.getInstance().getSize(); i++) {
			AirServerDevice air = AirOne.getInstance().getDevice(i);
			air.checked = false;
		}
	}

	/**
	 * unregister "FONE.AIRONE" Receiver
	 * 
	 * @return void
	 * @throws
	 */
	private void unregisterReceiver() {
		if (airone_receicer != null) {
			try {
				if (FonePlayerActivity.FonePlayerActivityInstance.get() != null) {
					FonePlayerActivity.FonePlayerActivityInstance.get().unregisterReceiver(airone_receicer);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			airone_receicer = null;
		}
	}

	static boolean isStoped = false;

	/**
	 * stop airone service and kill airone process
	 * 
	 * @return void
	 * @throws
	 */
	public static void Stop() {
		try {
			getInstance().unregisterReceiver();
			isStoped = true;
			ActivityManager am = (ActivityManager) ApplicationManage.getAplicationManageInstance().getSystemService(Activity.ACTIVITY_SERVICE);
			List<RunningServiceInfo> list = am.getRunningServices(100);
			for (RunningServiceInfo info : list) {
				if ("com.fone.player:airone".equals(info.process)) {
					L.i(TAG, "", "found process kill process");
					one = null;
					android.os.Process.killProcess(info.pid);
					datas.clear();
					break;
				}

			}
			one = null;
			// AirOne airone = getInstance();
			// if( airone != null && airone.conn != null ){
			// FonePlayerActivity.instance.unbindService( airone.conn );
			// Intent intent = new
			// Intent(FonePlayerActivity.instance,AironeService.class);
			// FonePlayerActivity.instance.stopService(intent);
			// }
		} catch (Exception e) {
			e.printStackTrace();
			L.i(TAG, "", "found process " + e.toString());
		}
	}

	/**
	 * if has login user change dlna server user to this user
	 * 
	 * @param dev
	 *            which device
	 * @return void
	 * @throws
	 */
	public static void loginTv(final AirServerDevice dev) {
		new Thread() {
			public void run() {
				try {
					// TODO 获取登录用户的用户信息，登录到TV
					// SnsSdkAccountInfo userInfo =
					// fn_Core.snsGetLoginUserInfo();
					// L.i(TAG, "userInfo.localAppID : ", userInfo.localAppID);
					// dev.logined = loginTvDevice(dev.server_uid,
					// userInfo.localAppID, userInfo.nickname,
					// userInfo.avatar);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}.start();
	}

	/**
	 * if has login user change dlna server user to this user
	 * 
	 * @param devuuid
	 *            device server_uid
	 * @param sid
	 *            user sq id
	 * @param nickname
	 * @param otherinfo
	 * @throws RemoteException
	 * @return boolean login state
	 * @throws
	 */
	public static boolean loginTvDevice(String devuuid, String sid, String nickname, String otherinfo) throws RemoteException {
		return one.getService().loginTvDevice(devuuid, sid, nickname, otherinfo);
	}

}
